
package com.superhelper.deliver.task;

import java.util.Date;

import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import com.superhelper.common.domain.Task;
import com.superhelper.common.mapper.TaskMapper;

public abstract class AbstractTaskRunnable implements Runnable {
    protected Task task;
    protected TaskMapper taskMapper;
    protected ApplicationContext appContext;

    protected Logger log = LoggerFactory.getLogger(this.getClass());

    public AbstractTaskRunnable(ApplicationContext appContext, TaskMapper taskMapper, Task task) {
        this.taskMapper = taskMapper;
        this.task = task;
        this.appContext = appContext;
    }

    /**
     * 任务执行前的处理,如果返回true，则可以继续逻辑处理
     * 
     * @return
     */
    protected boolean preExecute() {
        // occupy task
        // int updateResult = taskMapper.occupyTask(task.getId(),
        // task.getRetryTimes());
        // if (updateResult != 1) {
        // log.info("task occuppied by other thread, task stopped!");
        // return false;
        // }
        return true;
    }

    /**
     * 业务逻辑执行，如果执行成功，不需要后续处理则返回true;如果需要后续处理（如：需要重试），则返回false
     */
    protected abstract boolean execute();

    @Override
    public void run() {
        if (!preExecute()) {
            return;
        }
        if (execute()) {
            taskMapper.deleteTask(task.getId());
            return;
        }
        postExecute();
    }

    /**
     * 任务的后续处理
     */
    protected void postExecute() {
        if (task.getRetryTimes() >= 10) {
            log.warn("execute failed, task={}", task);
            return;// 暂时不删除这样情况的任务，方便观察这种情况发生的概率
        }
        // 10次，Interval为30秒时，各次间隔：1：30秒，2：4分钟，3：13分钟，4：32分钟，5：62分钟，6：108分钟，7：2小时，8：4小时，9：6小时，10：8小时，总共时长：25小时
        int delayLen = (int) Math.pow(task.getRetryTimes(), 2) * 15;
        Date nextTime = DateUtils.addSeconds(new Date(), delayLen);
        taskMapper.delayTask(task.getId(), nextTime);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.println(Math.pow(i, 2) * 15 / 60);
        }
    }
}
